﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RainEngine.Helper;

namespace RainEngine.Rendering
{
    /// <summary>
    /// 创建基本几何体球、立方体和矩形。
    /// 长宽总为1，中心位于0,0,0。 
    /// </summary>
    public static class MeshBuilder
    {
        const float HALF = 0.5f;
        
        #region 平面        

        /// <summary>
        /// 创建平面的四个顶点
        /// </summary>
        /// <param name="g">图形设备</param>
        /// <returns></returns>
        public static Mesh CreatePlane(GraphicsDevice g)
        {
            
            
            //  创建4个自定义格式的顶点。
            VertexPositionTextureNormalTangentBinormal[] vertices;
            vertices = new VertexPositionTextureNormalTangentBinormal[4];

            // 左下角顶点
            vertices[0].Position = new Vector3(-HALF, -HALF, 0);
            vertices[0].TextureCoordinate  = new Vector2(0, 1);                    

            //  左上角顶点
            vertices[1].Position = new Vector3(-HALF, HALF, 0);
            vertices[1].TextureCoordinate = new Vector2(0, 0);             

            // 右下角顶点
            vertices[2].Position = new Vector3(HALF, -HALF, 0);
            vertices[2].TextureCoordinate = new Vector2(1, 1);            

            // 右上角顶点
            vertices[3].Position = new Vector3(HALF, HALF, 0);
            vertices[3].TextureCoordinate = new Vector2(1, 0);

            // 四个顶点的切线、副法线和法线方向都是相同的
            vertices[0].Tanget = vertices[2].Tanget = vertices[3].Tanget = vertices[1].Tanget = Vector3.Right;
            vertices[0].Binormal = vertices[1].Binormal = vertices[2].Binormal = vertices[3].Binormal = Vector3.Up;
            vertices[0].Normal = vertices[1].Normal = vertices[2].Normal = vertices[3].Normal = Vector3.Backward;   

            // 创建并设置顶点缓存
            VertexBuffer vb = new VertexBuffer(g, typeof(VertexPositionTextureNormalTangentBinormal), 4, BufferUsage.WriteOnly );
            vb.SetData<VertexPositionTextureNormalTangentBinormal>(vertices);

            return new Mesh(PrimitiveType.TriangleStrip, vb, 4, 2);
        }


        #endregion

        /// <summary>
        /// 创建BillBoard
        /// </summary>
        /// <param name="g">图形设备</param>
        /// <returns></returns>
        public static Mesh CreatBillBoard(GraphicsDevice g)
        {
            //创建顶点数组
            VertexPositionTexture[] bbVertices = new VertexPositionTexture[4];
            Vector3 center = Vector3.Zero;

            // 左下顶点
            bbVertices[0].Position = center;
            bbVertices[0].TextureCoordinate = new Vector2(0, 1);

            //  左上顶点
            bbVertices[1].Position = center;
            bbVertices[1].TextureCoordinate = new Vector2(0, 0);

            // 右下顶点
            bbVertices[2].Position = center;
            bbVertices[2].TextureCoordinate = new Vector2(1, 1);

            // 右上顶点
            bbVertices[3].Position = center;
            bbVertices[3].TextureCoordinate = new Vector2(1, 0);

            // 创建顶点缓冲和索引缓冲
            VertexBuffer bbVertexBuffer = new VertexBuffer(g,typeof(VertexPositionTexture),bbVertices.Length, BufferUsage.WriteOnly);
            bbVertexBuffer.SetData<VertexPositionTexture>(bbVertices);

            return new Mesh(PrimitiveType.TriangleStrip, bbVertexBuffer, 4, 2);
        }

        #region  立方体
        /// <summary>
        /// 创建一个立方体。        
        /// </summary>
        /// <param name="g">图形设备</param>
        /// <returns></returns>
        public static Mesh CreateCube(GraphicsDevice g)
        {
            // 创建24个顶点。正方体有8个顶点，但是因为需要设置法线数据，所以必须定义24个顶点，每个面4个共24个，否则光照是不正确的
            VertexPositionTextureNormalTangentBinormal[] vertices = new VertexPositionTextureNormalTangentBinormal[24];

            // 设置8个顶点的位置
            Vector3 forwardBottomLeft = new Vector3(-HALF, -HALF, HALF);
            Vector3 forwardBottomRight = new Vector3(HALF, -HALF, HALF);
            Vector3 forwardUpperLeft = new Vector3(-HALF, HALF, HALF);
            Vector3 forwardUpperRight = new Vector3(HALF, HALF, HALF);

            Vector3 backBottomLeft = new Vector3(-HALF, -HALF, -HALF);
            Vector3 backBottomRight = new Vector3(HALF, -HALF, -HALF);
            Vector3 backUpperLeft = new Vector3(-HALF, HALF, -HALF);
            Vector3 backUpperRight = new Vector3(HALF, HALF, -HALF);


            #region 前面的顶点

            // 左下角顶点 - 0
            vertices[0].Position = forwardBottomLeft;
            vertices[0].TextureCoordinate = new Vector2(0, 1);
            vertices[0].Binormal = Vector3.Right;
            vertices[0].Tanget = Vector3.Up;
            vertices[0].Normal = Vector3.Backward;       

            //  左上角顶点 - 1
            vertices[1].Position = forwardUpperLeft;
            vertices[1].TextureCoordinate = new Vector2(0, 0);
            vertices[1].Binormal = Vector3.Right;
            vertices[1].Tanget = Vector3.Up;
            vertices[1].Normal = Vector3.Backward;       

            // 右下角顶点 - 2
            vertices[2].Position = forwardBottomRight;
            vertices[2].TextureCoordinate = new Vector2(1, 1);
            vertices[2].Binormal = Vector3.Right;
            vertices[2].Tanget = Vector3.Up;
            vertices[2].Normal = Vector3.Backward;       

            // 右上角顶点 - 3
            vertices[3].Position = forwardUpperRight;
            vertices[3].TextureCoordinate = new Vector2(1, 0);
            vertices[3].Binormal = Vector3.Right;
            vertices[3].Tanget = Vector3.Up;
            vertices[3].Normal = Vector3.Backward;       

            #endregion

            #region 后面的顶点

            // 左下角顶点-4
            vertices[4].Position = backBottomLeft;
            vertices[4].TextureCoordinate = new Vector2(0, 1);
            vertices[4].Normal = Vector3.Forward;
            vertices[4].Binormal = Vector3.Right;
            vertices[4].Tanget = Vector3.Down ;

            //  左上角顶点-5
            vertices[5].Position = backUpperLeft;
            vertices[5].TextureCoordinate = new Vector2(0, 0);
            vertices[5].Normal = Vector3.Forward;
            vertices[5].Binormal = Vector3.Right;
            vertices[5].Tanget = Vector3.Down;

            // 右下角顶点-6
            vertices[6].Position = backBottomRight;
            vertices[6].TextureCoordinate = new Vector2(1, 1);
            vertices[6].Normal = Vector3.Forward;
            vertices[6].Binormal = Vector3.Right;
            vertices[6].Tanget = Vector3.Down;

            // 右上角顶点-7
            vertices[7].Position = backUpperRight;
            vertices[7].TextureCoordinate = new Vector2(1, 0);
            vertices[7].Normal = Vector3.Forward;
            vertices[7].Binormal = Vector3.Right;
            vertices[7].Tanget = Vector3.Down;
            #endregion

            #region 左面的顶点

            // 左下角顶点-0
            vertices[8].Position = forwardBottomLeft;
            vertices[8].TextureCoordinate = new Vector2(0, 1);
            vertices[8].Normal = Vector3.Left ;
            vertices[8].Binormal = Vector3.Backward ;
            vertices[8].Tanget = Vector3.Up ;

            // 左上角顶点-1
            vertices[9].Position = forwardUpperLeft;
            vertices[9].TextureCoordinate = new Vector2(0, 0);
            vertices[9].Normal = Vector3.Left ;
            vertices[9].Binormal = Vector3.Backward;
            vertices[9].Tanget = Vector3.Up;

            // 右下角顶点-4
            vertices[10].Position = backBottomLeft;
            vertices[10].TextureCoordinate = new Vector2(1, 1);
            vertices[10].Normal = Vector3.Left ;
            vertices[10].Binormal = Vector3.Backward;
            vertices[10].Tanget = Vector3.Up;


            // 右上角顶点-5
            vertices[11].Position = backUpperLeft;
            vertices[11].TextureCoordinate = new Vector2(1, 0);
            vertices[11].Normal = Vector3.Left ;
            vertices[11].Binormal = Vector3.Backward;
            vertices[11].Tanget = Vector3.Up;
            #endregion

            #region 右面的顶点

            //  左下角顶点-2
            vertices[12].Position = forwardBottomRight;
            vertices[12].TextureCoordinate = new Vector2(0, 1);
            vertices[12].Normal = Vector3.Right ;
            vertices[12].Binormal = Vector3.Forward ;
            vertices[12].Tanget = Vector3.Up;

            // 左上角顶点-3
            vertices[13].Position = forwardUpperRight;
            vertices[13].TextureCoordinate = new Vector2(0, 0);
            vertices[13].Normal = Vector3.Right;
            vertices[13].Binormal = Vector3.Forward;
            vertices[13].Tanget = Vector3.Up;

            // 右下角顶点-6
            vertices[14].Position = backBottomRight;
            vertices[14].TextureCoordinate = new Vector2(1, 1);
            vertices[14].Normal = Vector3.Right;
            vertices[14].Binormal = Vector3.Forward;
            vertices[14].Tanget = Vector3.Up;


            // 右上角顶点-7
            vertices[15].Position = backUpperRight;
            vertices[15].TextureCoordinate = new Vector2(1, 0);
            vertices[15].Normal = Vector3.Right;
            vertices[15].Binormal = Vector3.Forward;
            vertices[15].Tanget = Vector3.Up;
            #endregion

            #region 上面的顶点

            //  左下角顶点-1
            vertices[16].Position = forwardUpperLeft;
            vertices[16].TextureCoordinate = new Vector2(0, 1);
            vertices[16].Normal = Vector3.Up;
            vertices[16].Binormal = Vector3.Right ;
            vertices[16].Tanget = Vector3.Forward ;

            // 左上角顶点-5
            vertices[17].Position = backUpperLeft;
            vertices[17].TextureCoordinate = new Vector2(0, 0);
            vertices[17].Normal = Vector3.Up;
            vertices[17].Binormal = Vector3.Right;
            vertices[17].Tanget = Vector3.Forward;

            // 右下角顶点-3
            vertices[18].Position = forwardUpperRight;
            vertices[18].TextureCoordinate = new Vector2(1, 1);
            vertices[18].Normal = Vector3.Up;
            vertices[18].Binormal = Vector3.Right;
            vertices[18].Tanget = Vector3.Forward;

            // 右上角顶点-7
            vertices[19].Position = backUpperRight;
            vertices[19].TextureCoordinate = new Vector2(1, 0);
            vertices[19].Normal = Vector3.Up;
            vertices[19].Binormal = Vector3.Right;
            vertices[19].Tanget = Vector3.Forward;
            #endregion

            #region 下面的顶点

            //  左下角顶点-0
            vertices[20].Position = forwardBottomLeft;
            vertices[20].TextureCoordinate = new Vector2(0, 1);
            vertices[20].Normal = Vector3.Down;
            vertices[20].Binormal = Vector3.Left ;
            vertices[20].Tanget = Vector3.Forward;

            // 左上角顶点-4
            vertices[21].Position = backBottomLeft;
            vertices[21].TextureCoordinate = new Vector2(0, 0);
            vertices[21].Normal = Vector3.Down;
            vertices[21].Binormal = Vector3.Left;
            vertices[21].Tanget = Vector3.Forward;

            // 右下角顶点-2
            vertices[22].Position = forwardBottomRight;
            vertices[22].TextureCoordinate = new Vector2(1, 1);
            vertices[22].Normal = Vector3.Down;
            vertices[22].Binormal = Vector3.Left;
            vertices[22].Tanget = Vector3.Forward;


            // 右上角顶点-6
            vertices[23].Position = backBottomRight;
            vertices[23].TextureCoordinate = new Vector2(1, 0);
            vertices[23].Normal = Vector3.Down;
            vertices[23].Binormal = Vector3.Left;
            vertices[23].Tanget = Vector3.Forward;
            #endregion

            //36个索引，每个面有两个三角形，每个三角形有3个索引，所以共36个索引，因为索引数量不会超过65536个，所以它的数据类型为ushort，可以减少发送到显卡的数据量
            ushort[] indices = {   
                                // 前面的正方形
                                0, 1, 2,
                                1, 3, 2,

                                // 后面的正方形
                                4, 6, 5,
                                6, 7, 5,

                                // 左面的正方形
                                9, 8, 10,
                                9, 10, 11,                                

                                // 右面的正方形
                                12, 13, 14,
                                13, 15, 14,

                                // 上面的正方形                                
                                 16, 17, 18,
                                 18, 17, 19,

                                // 下面的正方形                                
                                20, 22, 21,
                                22, 23, 21
                            };

            //创建顶点缓冲
            VertexBuffer vb = new VertexBuffer(g, typeof(VertexPositionTextureNormalTangentBinormal), vertices.Length, BufferUsage.WriteOnly);
            vb.SetData<VertexPositionTextureNormalTangentBinormal>(vertices);

            //设置顶点声明
            //VertexDeclaration vxDeclaration = new VertexDeclaration(VertexPositionNormalTangentBinormalTexture.VertexElements);

            //创建索引缓冲
            IndexBuffer ib = new IndexBuffer(g, typeof(ushort), indices.Length, BufferUsage.None);
            ib.SetData<ushort>(indices);

            return new Mesh(PrimitiveType.TriangleList, vb, ib, 24, 12);
        }
        #endregion
        
        #region 天空盒        

        /// <summary>
        /// 创建天空盒顶点和索引
        /// </summary>
        /// <param name="g">图形设备</param>
        /// <returns></returns>
        public static Mesh CreateSkybox(GraphicsDevice g)
        {
            //定义立方体的8个顶点。
            VertexPosition[] vertices = new VertexPosition[8];

            //8个顶点的位置坐标
            Vector3 forwardBottomLeft = new Vector3(-500, -500, -500);
            Vector3 forwardBottomRight = new Vector3(500, -500, -500);
            Vector3 forwardUpperLeft = new Vector3(-500, 500, -500);
            Vector3 forwardUpperRight = new Vector3(500, 500, -500);

            Vector3 backBottomLeft = new Vector3(-500, -500, 500);
            Vector3 backBottomRight = new Vector3(500, -500, 500);
            Vector3 backUpperLeft = new Vector3(-500, 500, 500);
            Vector3 backUpperRight = new Vector3(500, 500, 500);

            int i = 0;

            //相机前方的四个顶点
            vertices[i++] = new VertexPosition(forwardBottomLeft);
            vertices[i++] = new VertexPosition(forwardUpperLeft);
            vertices[i++] = new VertexPosition(forwardUpperRight);
            vertices[i++] = new VertexPosition(forwardBottomRight);

            //相机后方的四个顶点
            vertices[i++] = new VertexPosition(backBottomLeft);
            vertices[i++] = new VertexPosition(backUpperLeft);
            vertices[i++] = new VertexPosition(backUpperRight);
            vertices[i++] = new VertexPosition(backBottomRight);

            //36个索引
            ushort[] indices = {   
                                // 相机前方面的顶点索引
                                1, 2, 0,
                                0, 2, 3,

                                // 相机左方面的顶点索引
                                5, 1, 0,
                                0, 4, 5,

                                // 相机后方面的顶点索引
                                5, 4, 6,
                                6, 4, 7,                                

                                // 相机右方面的顶点索引
                                2, 6, 3,
                                3, 6, 7,

                                // 相机上方面的顶点索引
                                6, 2, 1,
                                1, 5, 6,

                                // 相机下方面的顶点索引
                                0, 3, 7,
                                7, 4, 0
                            };


            //定义完所有顶点后，要将它们放在VertexBuffer和IndexBuffer中发送到显存中。
            VertexBuffer skyboxVertexBuffer = new VertexBuffer(g, typeof(VertexPosition),vertices.Length ,BufferUsage.WriteOnly);
            skyboxVertexBuffer.SetData<VertexPosition>(vertices);

            IndexBuffer skyboxIndexBuffer = new IndexBuffer(g, typeof(ushort), indices.Length, BufferUsage.None);
            skyboxIndexBuffer.SetData(indices);
            

            //创建mesh，使用TriangleList绘制天空盒，共有8个顶点，绘制12个三角形
            return  new Mesh(PrimitiveType.TriangleList, skyboxVertexBuffer, skyboxIndexBuffer, 8, 12);
        }

        #endregion

        #region 球体
        /// <summary>
        /// 创建一个球体的顶点和索引。
        /// </summary>
        /// <param name="g">图形设备</param>
        /// <param name="sphereCylinders">水平切片数量</param>
        /// <param name="sphereSlices">竖直切片数量</param>
        /// <param name="radius">半径</param>
        /// <returns></returns>
        public static Mesh CreateSphere(GraphicsDevice g, byte sphereCylinders, byte sphereSlices, float radius)
        {
            //计算顶点和索引数量  
            int n_Vertices = (sphereCylinders + 1) * (sphereSlices + 1);
            int dwIndices = (3 * sphereCylinders * (sphereSlices + 1)) * 2;

            int[] indices = new int[dwIndices];
            VertexPositionTextureNormalTangentBinormal[] vertices = new VertexPositionTextureNormalTangentBinormal[n_Vertices];

            float StackAngle = MathHelper.Pi / (float)sphereCylinders;
            float SliceAngle = (float)(Math.PI * 2.0) / (float)sphereSlices;


            //生成球的顶点和索引  
            int vertcount = 0;            
            int Indexcount = 0;
            int wVertexIndex = 0;

            //计算每一条水平带
            for (int stack = 0; stack < (sphereCylinders + 1); stack++)
            {

                float r = (float)Math.Sin((float)stack * StackAngle);
                float y = (float)Math.Cos((float)stack * StackAngle);

                // 生成当前水平带上的竖直切片  
                for (int slice = 0; slice < (sphereSlices + 1); slice++)
                {
                    float x = r * (float)Math.Sin((float)slice * SliceAngle);
                    float z = r * (float)Math.Cos((float)slice * SliceAngle);

                    //计算每个顶点的位置、法线和纹理坐标
                    vertices[vertcount].Position = new Vector3(x * radius, y * radius, z * radius);
                    vertices[vertcount].Normal = Vector3.Normalize(new Vector3(x, y, z));
                    if (vertcount != 0)
                    {
                        vertices[vertcount].Tanget = vertices[vertcount].Position - vertices[vertcount - 1].Position;
                        vertices[vertcount].Binormal = Vector3.Cross(vertices[vertcount].Normal, vertices[vertcount].Tanget);
                    }
                    
                    vertices[vertcount].TextureCoordinate = new Vector2((float)slice / (float)sphereSlices, (float)stack / (float)sphereCylinders);
                    vertcount++;

                    //生成索引数据
                    if (stack < sphereCylinders)
                    {
                        indices[Indexcount++] = wVertexIndex + (sphereSlices + 1);
                        indices[Indexcount++] = wVertexIndex;
                        indices[Indexcount++] = wVertexIndex + 1;

                        indices[Indexcount++] = wVertexIndex + (sphereSlices);
                        indices[Indexcount++] = wVertexIndex;
                        indices[Indexcount++] = wVertexIndex + (sphereSlices + 1);

                        wVertexIndex++;
                    }
                                   
                }               
            }

            //VertexDeclaration vxDeclaration = new VertexDeclaration(g, VertexPositionTextureNormalTangentBinormal.VertexElements);
            VertexBuffer vb = new VertexBuffer(g, typeof(VertexPositionTextureNormalTangentBinormal), vertcount, BufferUsage.None);
            vb.SetData(vertices, 0, vertcount);

            IndexBuffer ib = new IndexBuffer(g, typeof(int), Indexcount, BufferUsage.None);
            ib.SetData(indices, 0, Indexcount);

            return new Mesh(PrimitiveType.TriangleList, vb, ib,vb.VertexCount ,ib.IndexCount /3);
        }
        #endregion                

        #region 天空球

        /// <summary>        
        /// 创建天空球顶点和索引
        /// </summary>        
        /// <param name="g">图形设备</param>
        /// <param name="cylinders">水平切片数量</param>
        /// <param name="slices">竖直切片数量</param>
        /// <param name="verticalRadians">北极到球最下面的夹角，使用PI表示一个完整的球，PI/2表示半球</param>
        /// <returns></returns>
        public static Mesh CreateSkyDome(GraphicsDevice g, int cylinders, int slices, float verticalRadians)
        {
            //===========================================================================
            //      
            //          x = r * cos(phi) * sin(theta)
            //          y = r * sin(phi) * sin(theta)
            //          z = r * cos(theta)
            //
            //          这里phi的范围是0 < phi <= 2Pi，theta范围是0 < theta < Pi
            //          半球的theta范围是[0, Pi/2]
            //          因为使用单位向量r=1，所以上述公式简化为：
            //
            //          x = cos(phi) * sin(theta)
            //          y = sin(phi) * sin(theta)
            //          z = cos(theta)
            //
            //------------------------------------------------------------------------------            
            //
            //        1) 我们必须考虑到XNA是右手坐标系，而+Z方向在屏幕之外，需要反转y/z坐标
            //
            //        2) 我们必须注意顶点是以逆时针顺序绘制的，因为我们是从天空球内部向外看的。
            //
            //        3) uv坐标必须正确计算。
            //
            //
            //          最终我们获得以下公式：
            //
            //          x =  cos(phi) * sin(theta)
            //          y =  cos(theta)
            //          z =  -1 * sin(phi) * sin(theta)
            //
            //===========================================================================
            int radius = 1000;

            
            int dwVertices = (slices + 1) * (cylinders + 1);
            int dwIndices = (3 * slices * (cylinders + 1)) * 2;
            int[] indices = new int[dwIndices];

            VertexPositionTexture[] vertices = new VertexPositionTexture[dwVertices];
            float stackAngle = verticalRadians / (float)slices;
            float sliceAngle = (float)(Math.PI * 2.0) / (float)cylinders;
            int wVertexIndex = 0;

            //生成顶点坐标、纹理坐标和索引
            int vertcount = 0;
            int Indexcount = 0;

            for (int stack = 0; stack < (slices + 1); stack++)
            {
                float r = (float)Math.Sin((float)stack * stackAngle);
                float y = radius*(float)Math.Cos((float)stack * stackAngle);

                for (int slice = 0; slice < (cylinders + 1); slice++)
                {
                    float z = radius * r * (float)Math.Sin((float)slice * sliceAngle) * -1;
                    float x = radius * r * (float)Math.Cos((float)slice * sliceAngle);

                    vertices[vertcount].Position = new Vector3(x, y, z);
                    vertices[vertcount].TextureCoordinate = new Vector2(1f - (float)slice / (float)cylinders, (float)stack / (float)slices);
                    vertcount++;
                    if (!(stack == (slices - 1)))
                    {
                        indices[Indexcount] = wVertexIndex + (cylinders + 1);
                        Indexcount++;
                        indices[Indexcount] = wVertexIndex + 1;
                        Indexcount++;
                        indices[Indexcount] = wVertexIndex;
                        Indexcount++;
                        indices[Indexcount] = wVertexIndex + (cylinders);
                        Indexcount++;
                        indices[Indexcount] = wVertexIndex + (cylinders + 1);
                        Indexcount++;
                        indices[Indexcount] = wVertexIndex;
                        Indexcount++;
                        wVertexIndex++;
                    }
                }
            }

            //创建顶点缓冲
            VertexBuffer skyDomeVertexBuffer = new VertexBuffer(g, typeof(VertexPositionTexture), dwVertices, BufferUsage.WriteOnly);
            skyDomeVertexBuffer.SetData<VertexPositionTexture>(vertices);

            //创建索引缓冲
            IndexBuffer skyDomeIndexBuffer = new IndexBuffer(g, typeof(int), Indexcount, BufferUsage.None);
            skyDomeIndexBuffer.SetData(indices, 0, Indexcount);

            //创建mesh，使用TriangleList绘制天空球
            return new Mesh(PrimitiveType.TriangleList, skyDomeVertexBuffer, skyDomeIndexBuffer, dwVertices, dwIndices / 3);
        }

        #endregion

        #region 水面

        /// <summary>
        /// 创建水面顶点
        /// </summary>
        /// <param name="graphicsDevice">图形设备</param>
        /// <param name="Width">水面宽度</param>
        /// <param name="Height">水面高度</param>
        public static Mesh CreateWater(GraphicsDevice graphicsDevice, int Width, int Height)
        {
            //定义四个顶点创建覆盖整个水面的两个三角形。
            VertexPositionTexture[] waterVertices = new VertexPositionTexture[4];

            waterVertices[0] = new VertexPositionTexture(new Vector3(-Width/2, 0, -Height/2), new Vector2(0, 0));
            waterVertices[2] = new VertexPositionTexture(new Vector3(-Width/2, 0, Height/2), new Vector2(0, 1));
            waterVertices[1] = new VertexPositionTexture(new Vector3(Width/2, 0, -Height/2), new Vector2(1, 0));            
            waterVertices[3] = new VertexPositionTexture(new Vector3(Width/2, 0, Height/2), new Vector2(1, 1));

            VertexBuffer waterVertexBuffer = new VertexBuffer(graphicsDevice,typeof(VertexPositionTexture),4,BufferUsage.WriteOnly);
            waterVertexBuffer.SetData(waterVertices);            

            //创建水面的mesh
            return new Mesh(PrimitiveType.TriangleStrip, waterVertexBuffer, 4, 2);
        }

        #endregion

        #region 海面 
        
        /// <summary>
        /// 创建海面的顶点缓冲和索引缓冲
        /// </summary>        
        public static Mesh CreateOcean(GraphicsDevice g,int oceanWidth,int oceanHeight)
        {
            // 创建顶点
            int verticesLength=oceanWidth * oceanHeight;
            // 顶点偏移，可以将中心位置移动至海面中央
            Vector3 offset = new Vector3(-oceanWidth / 2,0, oceanHeight / 2);
            VertexPositionTexture[] oceanVertices = new VertexPositionTexture[verticesLength];

            int i = 0;
            for (int z = 0; z < oceanHeight; z++)
            {
                for (int x = 0; x < oceanWidth; x++)
                {
                    Vector3 position = new Vector3(x, 0, -z)+offset ;
                    Vector2 texCoord = new Vector2((float)x / oceanWidth, (float)z / oceanHeight);

                    oceanVertices[i++] = new VertexPositionTexture(position, texCoord);
                }
            }            

            // 创建索引
            int[] oceanIndices = new int[(oceanWidth) * 2 * (oceanHeight - 1)];

            i = 0;
            int y = 0;
            while (y < oceanHeight - 1)
            {
                for (int x = 0; x < oceanWidth; x++)
                {
                    oceanIndices[i++] = x + y * oceanWidth;
                    oceanIndices[i++] = x + (y + 1) * oceanWidth;
                }
                y++;

                if (y < oceanHeight - 1)
                {
                    for (int x = oceanWidth - 1; x >= 0; x--)
                    {
                        oceanIndices[i++] = x + (y + 1) * oceanWidth;
                        oceanIndices[i++] = x + y * oceanWidth;
                    }
                }
                y++;
            }

            VertexBuffer oceanVertexBuffer = new VertexBuffer(g, typeof(VertexPositionTexture), verticesLength, BufferUsage.WriteOnly);
            oceanVertexBuffer.SetData(oceanVertices);

            IndexBuffer oceanIndexBuffer = new IndexBuffer(g, typeof(int), oceanIndices.Length, BufferUsage.WriteOnly);
            oceanIndexBuffer.SetData(oceanIndices);

            return new Mesh(PrimitiveType.TriangleStrip, oceanVertexBuffer, oceanIndexBuffer, verticesLength, oceanWidth * 2 * (oceanHeight - 1) - 2);
        }

        #endregion              
    }
}
